 page
****************************
*                          *
*    read address field    *
*        subroutine        *
*    (16-sector format)    *
*                          *
****************************
*                          *
*    reads volume, track   *
*        and sector        *
*                          *
*    on entry ----     *
*                          *
*  xreg: slotnum times $10 *
*                          *
*  read mode (q6l, q7l)    *
*                          *
*    on exit -----     *
*                          *
*  carry set if error.     *
*                          *
*  if no error:            *
*    a-reg holds $aa.      *
*    y-reg holds $00.      *
*    x-reg unchanged.      *
*    carry clear.          *
*                          *
*    csstv holds chksum,   *
*      sector, track, and  *
*      volume read.        *
*                          *
*    uses temps count,     *
*      last, csum, and     *
*      4 bytes at csstv.   *
*                          *
*     expects ----     *
*                          *
*   original 10-sector     *
*  normal density nibls    *
*   (4-bit), odd bits,     *
*   then even.             *
*                          *
*     caution ----     *
*                          *
*         observe          *
*    'no page cross'       *
*      warnings on         *
*    some branches!!       *
*                          *
*     assumes ----     *
*                          *
*    1 usec cycle time     *
*                          *
****************************
rdadr16 ldy #$fc
 sty count ;'must find' count.
rdasyn iny
 bne rda1 ;low order of count.
 inc count ;(2k nibls to find
 beq rderr ; adr mark, else err)
rda1 lda q6l,x ;read nibl.
 bpl rda1 ;*** no page cross! ***
rdasn1 cmp #$d5 ;adr mark 1?
 bne rdasyn  ;(loop if not)
 nop ;added nibl delay.
rda2 lda q6l,x
 bpl rda2 ;*** no page cross! ***
 cmp #$aa ;adr mark 2?
 bne rdasn1 ; (if not, is it am1?)
 ldy #$3 ;index for 4-byte read.
*            (added nibl delay)
rda3 lda q6l,x
 bpl rda3 ;*** no page cross! ***
 cmp #$96 ;adr mark 3?
 bne rdasn1 ; (if not, is it am1?)
 sei ;no interupts until address is tested.(carry is set) 
 lda #$0 ;init checksum.
rdafld sta csum
rda4 lda q6l,x ;read 'odd bit' nibl.
 bpl rda4 ;*** no page cross! ***
 rol a ;align odd bits, '1' into lsb.
 sta last ; (save them)
rda5 lda q6l,x ;read 'even bit' nibl.
 bpl rda5 ;*** no page cross! ***
 and last ;merge odd and even bits.
 sta csstv,y ;store data byte.
 eor csum
 dey
 bpl rdafld ;loop on 4 data bytes.
 tay ;if final checksum
 bne rderr ;nonzero, then error.
rda6 lda q6l,x ;first bit-slip nibl.
 bpl rda6 ;*** no page cross! ***
 cmp #$de
 bne rderr ;error if nonmatch.
 nop ;delay
rda7 lda q6l,x ;second bit-slip nibl.
 bpl rda7 ;*** no page cross! ***
 cmp #$aa
 bne rderr ;error if nonmatch.
 clc ;clear carry on
 rts ; normal read exits.
rderr sec
 rts
 page
**************************
*                        *
*     read subroutine    *
*   (16-sector format)   *
*                        *
**************************
*                        *
*   reads encoded bytes  *
*  into nbuf1 and nbuf2  *
*                        *
*  first reads nbuf2     *
*          high to low,  *
*  then reads nbuf1      *
*          low to high.  *
*                        *
*    on entry ----   *
*                        *
*  x-reg: slotnum        *
*         times $10.     *
*                        *
*  read mode (q6l, q7l)  *
*                        *
*    on exit -----   *
*                        *
*  carry set if error.   *
*                        *
*  if no error:          *
*     a-reg holds $aa.   *
*     x-reg unchanged.   *
*     y-reg holds $00.   *
*     carry clear.       *
*    caution -----   *
*                        *
*        observe         *
*    'no page cross'     *
*      warnings on       *
*    some branches!!     *
*                        *
*    assumes ----    *
*                        *
*   1 usec cycle time    *
*                        *
**************************
read16 txa ;get slot #.
 ora #$8c ;prepare mods to read routine.
 sta rd4+1 ;warning: the read routine is self modified!!!
 sta rd5+1
 sta rd6+1
 sta rd7+1
 sta rd8+1
 lda buf ;modify storage addresses also.
 ldy buf+1
 sta ref3+1
 sty ref3+2
 sec
 sbc #$54
 bcs rd16b ;branch if no borrow.
 dey
rd16b sta ref2+1
 sty ref2+2
 sec
 sbc #$57
 bcs rd16c ;branch if no borrow.
 dey
rd16c sta ref1+1
 sty ref1+2
 ldy #$20 ;'must find count'
rsync dey
 beq rderr2 ;branch if can't find data header marks.
rd1 lda q6l,x
 bpl rd1
rsync1 eor #$d5 ;first data mark.
 bne rsync
 nop ;waste a little time...
rd2 lda q6l,x
 bpl rd2
 cmp #$aa ;data mark 2
 bne rsync1 ;if not, check for first again.
 nop
rd3 lda q6l,x
 bpl rd3
 cmp #$ad ;data mark 3
 bne rsync1 ;if not, check for data mark 1 again.
 ldy #$aa
 lda #0
rdata1 sta wtemp ;use zpage for checksum keeping.
rd4 ldx $c0ec ;warning: self modified.
 bpl rd4
 lda dnibl,x
 sta nbuf2-$aa,y ;save the two-bit groups in nbuf.
 eor wtemp ;update checksum.
 iny ;bump to next nbuf position.
 bne rdata1 ;loop for all $56 two-bit groups.
 ldy #$aa ;now read directly into user buffer.
 bne rd5 ;branch always taken!!!
*
rderr2 sec
 rts
*
ref1 sta $1000,y ;warning: self modified!
*
rd5 ldx $c0ec
 bpl rd5
 eor dnibl,x ;get actual 6-bit data from dnib table.
 ldx nbuf2-$aa,y ;get associated two-bit pattern.
 eor dnibl2,x ;and combine to form whole byte.
 iny
 bne ref1 ;loop for $56 bytes.
 pha ;save this byte for now, no time to store...
 and #$fc ;strip low bits...
 ldy #$aa ;prepare for next $56 bytes.
rd6 ldx $c0ec
 bpl rd6
 eor dnibl,x
 ldx nbuf2-$aa,y
 eor dnibl3,x
ref2 sta $1000,y ;warning: self modified.
 iny
 bne rd6 ;loop until this group of $56 read in.
*
rd7 ldx $c0ec
 bpl rd7
 and #$fc
 ldy #$ac ;last group is $54 long.
rdata2 eor dnibl,x
 ldx nbuf2-$ac,y
 eor dnibl4,x ;combine to form full byte.
ref3 sta $1000,y
rd8 ldx $c0ec ;warning: self modified.
 bpl rd8
 iny
 bne rdata2
 and #$fc
 eor dnibl,x ;check sum ok?
 bne rderr1 ;branch if not.
 ldx slotz ;test end marks.
rd9 lda q6l,x
 bpl rd9
 cmp #$de
 clc
 beq rdok ;branch if good trailer...
rderr1 sec
rdok pla ;place last byte into user buffer.
 ldy #$55
 sta (buf),y
 rts
*
 page
*
* this subroutine sets the slot dependent track
* location.
*
settrk jsr drvindx ;get index to drive number.
 sta drv0trk,x
 rts
*****************************************
*
* subr to tell if motor is stopped
*
* if motor is stopped, controller's
* shift reg will not be changing.
*
* return y=0 and zero flag set if it is stopped.
*
*****************************************
chkdrv ldx slotz
chkdrv0 ldy #0 ;init loop counter
chkdrv1 lda q6l,x ;read the shift reg
 jsr ckdrts ;delay
 pha
 pla ;more delay
 cmp q6l,x ;has shift reg changed?
 bne ckdrts ;yes, motor is moving
 lda #ibnodrv ;anticipate error.
 dey ;no,dec retry counter
 bne chkdrv1 ;and try 256 times
ckdrts rts ;then return
*
drvindx pha  ;preserve acc.
 lda unitnum 
 lsr a
 lsr a
 lsr a
 lsr a 
 cmp #$8
 and #$7
 rol a
 tax  ;into x for index to table
 pla  ;restore acc.
 rts
 page
************************
*                      *
*      write subr      *
*  (16-sector format)  *
*                      *
************************
*                      *
*   writes data from   *
*    nbuf1 and buf     *
*                      *
*  first nbuf2,        *
*      high to low.    *
*  then direct from    * 
*  (buf), low to high. * 
* self modified code!! *
*   on entry ----  *
*                      *
*   x-reg: slotnum     *
*        times $10.    *
*                      *
*                      *
*   on exit -----  *
*                      *
*  carry set if error. *
*   (w prot violation) *
*                      *
*  if no error:        *
*                      *
*    a-reg uncertain.  *
*    x-reg unchanged.  *
*    y-reg holds $00.  *
*    carry clear.      *
*                      *
*   assumes ----   *
*                      *
*  1 usec cycle time   *
*                      *
************************
write16 sec ;anticipate wprot err.
 lda q6h,x
 lda q7l,x ;sense wprot flag.
 bpl wr16
 jmp wexit ;exit if write protected
wr16 lda nbuf2
 sta wtemp
 lda #$ff ;sync data.
 sta q7h,x  ;(5) goto write mode
 ora q6l,x  ;(4)
 ldy #$4  ;(2) for five nibls.
 nop ;(2)
 pha ;(3)
 pla ;(4)
wsync pha ;(3) exact timing.
 pla ;(4) exact timing.
 jsr wnibl7 ;(13,9,6)  write sync.
 dey ;(2)
 bne wsync ;(3-)  must not cross page!
 lda #$d5 ;(2)  1st data mark.
 jsr wnibl9 ;(15,9,6)
 lda #$aa ;(2)  2nd data mark.
 jsr wnibl9 ;(15,9,6)
 lda #$ad ;(2)  3rd data mark.
 jsr wnibl9 ;(15,9,6)
 tya ;(2) zero checksum 
 ldy #$56 ;(2) nbuf2 index
 bne wdata1 ;(3)branch always taken. 
wdata0 lda nbuf2,y ;(4) prior 6-bit nibl. 
wdata1 eor nbuf2-1,y ;(5) xor with current. 
 tax ;(2) index to 7-bit nibl (nbuf2 must be on page boundary). 
 lda nibl,x ;(4) must not cross page boundary 
 ldx slotz ;(3) restore slot index. 
 sta q6h,x ;(5) store encoded byte.
 lda q6l,x ;(4) time must = 32 us per byte!
 dey ;(2)
 bne wdata0 ;(3-) must not cross page boundary 
 lda wtemp ;(3) get prior nibl (from nbuf2).
wrefd1 ldy #0 ;(2) warning: load value modified by prenib! 
wdata2 equ *
wrefa1 eor $1000,y ;(4) warning: address modified by prenib!
 and #$fc ;(2)
 tax ;(2) index to nibl table
 lda nibl,x ;(4)
wrefd2 ldx #$60 ;(2) warning: load value modified by prenib
 sta q6h,x ;(5) write nibl.
 lda q6l,x ;(4) handshake.
wrefa2 lda $1000,y ;(4) prior nibl. warning: address modified by prenib.
 iny ;(2) all done with this page?
 bne wdata2 ;(3-) loop until page end.
*
 lda midnib1 ;(3) get next (precalculated and translated) nibl.
 beq wdone ;(2+) branch if code writen was page aligned.
 lda yend ;(3) get byte address of last byte to be written.
 beq wdata4 ;(2+) branch if only 1 byte left to write.
 lsr a ;(2) test for odd or even last byte (carry set or clear)
 lda midnib1 ;(3) restore nibl to acc.
 sta q6h,x ;(5)
 lda q6l,x ;(4)
 lda midnib2 ;(3) =byte 0 of second page. xor'd with byte 1 if above test set carry.
 nop ;(2) waste time.
 iny ;(2) y=1
 bcs wrtodd ;(2+) branch if last byte to be odd.
*
wdata3 equ *
wrefa3 eor $1100,y ;(4) warning: address modified by prenib.
 and #$fc ;(2) strip low 2 bits.
 tax ;(2) index to nibl table.
 lda nibl,x ;(4) get nibl.
wrefd3 ldx #$60 ;(2) restore slot index. warning: modified by prenib.
 sta q6h,x ;(5)
 lda q6l,x ;(4)
wrefa4 lda $1100,y ;(4) warning: modified by prenib.
 iny ;(2) got prior nibl, bump to next.
wrefa5 eor $1100,y ;(4) warning: modified by prenib.
wrtodd cpy yend ;(3) set carry if this is last nibl.
 and #$fc ;(2)
 tax ;(2) 
 lda nibl,x ;(4)
wrefd4 ldx #$60 ;(2) restore slot. warning: modified by prenib. 
 sta q6h,x ;(5) 
 lda q6l,x ;(4) 
wrefa6 lda $1100,y ;(4) get prior. warning: these warnings are all the same.
 iny ;(2) 
 bcc wdata3 ;(3-) branch if that was not the last.
 bcs wdne1 ;(3) waste 3 cycles, branch always
wdne1 bcs wdone ;(3) branch always
*
wdata4 dfb $ad,midnib1,$00 ;(4) absolute reference to zero page.
 sta q6h,x ;(5)
 lda q6l,x ;(4)
 pha ;(3) waste 14 us total.
 pla ;(4)
 pha ;(3)
 pla ;(4) 
wdone ldx lstnib ;(3) use last nibl (anded with $fc) for checksum.
 lda nibl,x ;(4)
wrefd5 ldx #$60 ;(2) restore slot. warning: see above warnings...
 sta q6h,x ;(5) 
 lda q6l,x ;(4)
 ldy #0 ;(2) set y to index end mark table. 
 pha ;(3) waste another 11 us. 
 pla ;(4) 
 nop ;(2) 
 nop ;(2) 
wrtendmk lda endmrks,y ;(4) dm4, dm5, dm6, and turn off byte. 
 jsr wnibl ;(15,6)    write it.
 iny ;(2)
 cpy #4 ;(2) have all end marks been written? 
 bne wrtendmk ;(3)
 clc ;(2,9) 
wexit lda q7l,x ;out of write mode.
 lda q6l,x ;to read mode.
 rts ;return from write.
*
****************************
*                           *
*   7-bit nibl write subrs  *
*                           *
*   a-reg or'd prior exit   *
*       carry cleared       *
*                           *
****************************
wnibl9 clc ;(2)  9 cycles, then write.
wnibl7 pha ;(3)  7 cycles, then write.
 pla ;(4)
wnibl sta q6h,x ;(5)  nibl write sub.
 ora q6l,x ;(4)  clobbers acc, not carry.
 rts ;(6) 
*
 page
****************************
*                          *
*    preniblize subr       *
*   (16-sector format)     *
*                          *
****************************
*                          *
*  converts 256 bytes of   *
*  user data in (buf) into *
*  6 bit nibls into nbuf2  *
*  high 6 bits are trans-  * 
*  lated directly by the   *
*  write routines.         *
*                          *
*     on entry ----    *
*                          *
*  buf is 2-byte pointer   *
*    to 256 bytes of user  *
*    data.                 *
*                          *
*     on exit -----    *
*                          *
*  a,x,y undefined.        *
*  write routine modified  *
*  to do direct conversion *
*  of high 6 bits of users *
*  buffer data.            *
****************************
prenib16 lda buf ;first self modify addresses so we can be fast! 
 ldy buf+1 ;y contains high order address. 
 clc ;all offsets are -$aa... 
 adc #2 ;the highest set is buf+$ac 
 bcc prenib1 ;branch if no carry. 
 iny ;otherwise add carry to high address. 
prenib1 sta prn3+1 ;self mod 3 
 sty prn3+2 
 sec 
 sbc #$56 ;middle set is buf+$56 
 bcs prenib2 ;branch if no borrow 
 dey ;otherwise deduct from high..
prenib2 sta prn2+1 ;self mod 2. 
 sty prn2+2 
 sec
 sbc #$56 ;low set is exactly buf.
 bcs prenib3
 dey
prenib3 sta prn1+1 ;self mod 1.
 sty prn1+2
*  
 ldy #$aa  ;count up to 0. 
prenib4 equ * 
prn1 lda $1000,y ;fetch byte from lowest group. warning: self modified. 
 and #$3 ;strip high 6 bits. 
 tax ;index to 2 bit equiv.
 lda twobit1,x 
 pha ;save pattern 
prn2 lda $1056,y ;fetch from middle group 
 and #3 
 tax 
 pla ;restore pattern.
 ora twobit2,x ;combine second group with first. 
 pha ;save new pattern. 
prn3 lda $10ac,y ;get highest group.
 and #3 
 tax 
 pla ;restore new pattern. 
 ora twobit3,x ;and form final nibl. 
 pha
 tya
 eor #$ff
 tax
 pla
 sta nbuf2,x ;save in nibl buffer! 
 iny ;bump to next set. 
 bne prenib4 ;loop until all $56 nibls formed. 
 ldy buf ;now prepare data bytes for write16 routine.
 dey ;prepare end addr.
 sty yend
 lda buf 
 sta wrefd1+1 ;warning: the following storage addresses starting
 beq wmod1 ; with 'wref' are referces into code space,
 eor #$ff ; changed by this routine.
 tay ;index to last byte of page pointed to by buf.
 lda (buf),y ;pre-niblize the last byte of the page with
 iny ; the first byte of the next page.
 eor (buf),y
 and #$fc
 tax
 lda nibl,x ;get disk 7-bit nibl equivalent.
wmod1 sta midnib1
 beq wmod3 ;branch if data to be written is page aligned.
 lda yend ;find out if last byte is even or odd address.
 lsr a ;shift even/oddness into carry
 lda (buf),y ;if even, then leave in tact.
 bcc wmod2 ;branch if odd.
 iny ;if even, then pre-xor with byte 1.
 eor (buf),y
wmod2 sta midnib2 ;save result for write routine.
wmod3 ldy #$ff ;index to last byte of data to be writen
 lda (buf),y ; to be used as checksum.
 and #$fc ;strip extra bits
 sta lstnib ;save it.
 ldy buf+1 ;now modify address reference to user data.
 sty wrefa1+2
 sty wrefa2+2
 iny
 sty wrefa3+2
 sty wrefa4+2
 sty wrefa5+2
 sty wrefa6+2
 ldx slotz ;and lastly index references to controller.
 stx wrefd2+1 
 stx wrefd3+1 
 stx wrefd4+1 
 stx wrefd5+1 
 rts  ;all done.
*
chkprev eor iobpdn ;same slot as last?
 asl a
 beq chkpv2 
 lda #01 
 sta montimeh
chkpv1 lda iobpdn
 and #$70
 tax
 beq chkpv2 ;branch if no previous ever (boot only)
 jsr chkdrv0 ;find out if previous drive running. 
 beq chkpv2 ;branch if stopped.
 lda #1 ;waste some time.
 jsr mswait
 lda montimeh
 bne chkpv1
chkpv2 rts
*
* ----------------- see rev notes 14, 18 & 70 -------------
rsetphse equ *
 lda unitnum ;get unit number
 and #$7f ;map off hi bit
 tax
*
* clear all the phases and force read mode
*
*
* patch 76 part 2. part 1 is in xrw1.
 skp 1
 lda phaseoff+0,x ;make sure all motor phases
 lda phaseoff+2,x ;  are off.
 lda phaseoff+4,x
 lda phaseoff+6,x
 rts
* ---------------------------------------------------------
docheck equ *
 lda dhpcmd ;get the command number
 cmp #maxcmd ;is the command allowable?
 bcs dochkbad ;branch if not!
 lda bloknml
 ldx bloknmh
 stx ibtrk ;calculate block's track & sector.
 beq dochkok ;branch if block # in range.
 dex ;else test further
 bne dochkbad ;bad range
 cmp #$18 ;must be <$118
 bcc dochkok
dochkbad sec ;set carry for an error
 rts
*
dochkok clc ;no error
 rts
